package cn.com.anypay.manager.service.impl;

import cn.com.anypay.manager.config.SecurityConfig;
import cn.com.anypay.manager.service.RedirectValidationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.net.URL;

/**
 * 重定向验证服务实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RedirectValidationServiceImpl implements RedirectValidationService {

    private final SecurityConfig securityConfig;

    @Override
    public boolean isValidRedirectUrl(String url) {
        return validateRedirectUrl(url).isValid();
    }

    @Override
    public ValidationResult validateRedirectUrl(String url) {
        try {
            // 基本格式验证
            if (url == null || url.trim().isEmpty()) {
                return ValidationResult.invalid("URL不能为空");
            }

            // URL长度限制
            if (url.length() > securityConfig.getRedirect().getMaxUrlLength()) {
                return ValidationResult.invalid("URL长度超过限制");
            }

            // 处理相对路径URL
            if (url.startsWith("/")) {
                log.debug("Relative URL validation passed: {}", url);
                return ValidationResult.valid();
            }

            // 解析绝对URL
            URL parsedUrl = new URL(url);
            String protocol = parsedUrl.getProtocol();
            String hostname = parsedUrl.getHost();

            // 协议验证
            if (!securityConfig.isAllowedProtocol(protocol)) {
                if (securityConfig.getRedirect().isLogRejected()) {
                    log.warn("Invalid protocol rejected: {}", protocol);
                }
                return ValidationResult.invalid("不允许的协议: " + protocol);
            }

            // 域名验证
            if (securityConfig.getRedirect().isStrictMode() && !securityConfig.isAllowedDomain(hostname)) {
                if (securityConfig.getRedirect().isLogRejected()) {
                    log.warn("Domain not in whitelist rejected: {}", hostname);
                }
                return ValidationResult.invalid("域名不在白名单中: " + hostname);
            }

            // 检查是否为本地地址或私有地址（可选，根据需要开启）
            if (isLocalOrPrivateAddress(hostname)) {
                log.info("Local or private address allowed: {}", hostname);
            }

            log.debug("URL validation passed: {}", url);
            return ValidationResult.valid();

        } catch (Exception e) {
            log.error("URL validation failed for: {}", url, e);
            return ValidationResult.invalid("URL格式错误: " + e.getMessage());
        }
    }

    /**
     * 检查是否为本地或私有地址
     *
     * @param hostname 主机名
     * @return 是否为本地或私有地址
     */
    private boolean isLocalOrPrivateAddress(String hostname) {
        if (hostname == null) {
            return false;
        }

        // 检查localhost和127.0.0.1
        if ("localhost".equals(hostname) || "127.0.0.1".equals(hostname)) {
            return true;
        }

        // 检查IPv4私有地址范围
        if (hostname.matches("^10\\.|^192\\.168\\.|^172\\.(1[6-9]|2[0-9]|3[01])\\.")) {
            return true;
        }

        // 检查IPv6本地地址
        if (hostname.startsWith("::1") || hostname.startsWith("fe80:")) {
            return true;
        }

        return false;
    }
}